home *** CD-ROM | disk | FTP | other *** search
- /* MerlinFLI - Rainer Trunz, Januar 1995
-
- This file, read.c, was taken over from the original xflick
- source with a lot(!) of modifications - see comments and
- code, the include file change below, and a call to the
- new error/exit routine 'Quit' instead of 'xferror'.
-
- Here is the original comment:
-
- xflick - Ron Schnell, March, 1991
-
- This code is provided as is, with no warrantees, expressed
- or implied. I believe this code to be free of encumbrance,
- and offer it to the public domain. I ask, however, that
- this paragraph and my name be retained in any modified
- versions of the file you may make, and that you notify me
- of any improvements you make to the code.
-
- Ron Schnell (ronnie@sos.com)
-
- The following changes are from Michael Pall
- (pall@rz.uni-karlsruhe.de) Mar 25-28 1991:
-
- Lots of bugfixes and changes to the structure of the files.
- The interpretation part is now in this file.
-
- This is read.c, the functions which read in
- FLI structures in a machine independent format.
- */
-
- #include <proto/dos.h>
-
- #include "eflick.h"
- #include "proto.h"
-
- #include <sys/types.h>
- #include <stdlib.h>
- #include <string.h>
-
- enum {
- NO_ERR = 1,
- MEM_ERR,
- GFX_ERR,
- INT_ERR,
- SYS_ERR,
- REN_ERR,
- DBL_ERR,
- SCR_ERR,
- REQ_ERR,
- WIN_ERR,
- FND_ERR,
- PIP_ERR,
- DRI_ERR,
- PAR_ERR,
- MPG_ERR,
- RNG_ERR,
- GET_ERR,
- BRK_ERR,
- GAD_ERR,
- VIS_ERR,
- MEN_ERR
- };
-
- #ifndef TRUE
- #define TRUE 1
- #define FALSE 0
- #endif
-
- #define grab_short(p)\
- ({int i=*((unsigned char *)p++); i |= *((unsigned char *)p++) << 8; i;})
-
- #define get_short(p) (grab_short(p) & 0x0000ffff)
-
- #define get_long(p) grab_short(p) + (grab_short(p) << 16)
-
- /* #define DEBUGGING 1 */
-
- extern int verbose;
- extern void Quit(int);
-
- /*****************************************************************************
- *
- * get_short - PeeCee-Schrott für baserel Gnu-C ;-(((
- *
- * ©`95 Rainer F. Trunz. Geschrieben für Gnu-C 2.3.3 !
- *
- * strange,strange,strange.. funktioniert mal, mal nicht #!?
- *****************************************************************************/
- /*
- #define get_short(x) \
- ({int res; unsigned char *arg = (x); \
- __asm __volatile (" \
- moveq #0,d0; movel %1,a0; \
- moveb a0@+,d0; \
- moveb a0@+,d1; \
- lslw #8,d1;orw d1,d0; \
- movel a0,%1; \
- movel d0,%0" \
- : "=f" (res) * Output * \
- : "r" (arg) * Input * \
- : "d0", "d1", "a0"); res;})
-
- #define get_long(x) \
- ({int res; unsigned char *arg = (x); \
- __asm __volatile (" \
- moveq #0,d0; movel %1,a0; \
- moveb a0@+,d0; \
- moveb a0@+,d1; \
- lslw #8,d1;orw d1,d0;swap d0;\
- moveb a0@+,d0; \
- moveb a0@+,d1; \
- lslw #8,d1;orw d1,d0;swap d0;\
- movel a0,%1; \
- movel d0,%0" \
- : "=f" (res) * Output * \
- : "r" (arg) * Input * \
- : "d0", "d1", "a0"); res;})
- */
-
- void
- read_flihead (BPTR fd, struct fli_header *header)
- {
- unsigned char *buf, *sbf;
- int i;
-
- if (!(buf = (unsigned char *)malloc(SIZE_HEADER)))
- Quit (MEM_ERR);
-
- sbf = buf;
-
- if (FRead (fd, buf, SIZE_HEADER, 1) < 1)
- Quit (GET_ERR);
-
- header->fhd_size = get_long(buf);
-
- header->fhd_magic = get_short(buf);
-
- header->fhd_frames = get_short(buf);
-
- header->fhd_width = get_short(buf);
-
- header->fhd_height = get_short(buf);
-
- header->fhd_gap = get_short(buf);
-
- header->fhd_flags = get_short(buf);
-
- header->fhd_speed = get_short(buf);
-
- header->fhd_next = get_long(buf);
-
- header->fhd_frit = get_long(buf);
-
- memcpy (buf, header->fhd_expand, FHD_EXPAND_SIZE);
-
- free (sbf);
-
- /* Seek (fd, SIZE_HEADER, OFFSET_BEGINNING); */
-
- if (verbose) {
- Printf ("header->fhd_size: %ld\n", header->fhd_size);
- Printf ("header->fhd_magic: 0x%lx\n", header->fhd_magic);
- Printf ("header->fhd_frames: %ld\n", header->fhd_frames);
- Printf ("header->fhd_width: %ld\n", header->fhd_width);
- Printf ("header->fhd_height: %ld\n", header->fhd_height);
- Printf ("header->fhd_gap: 0x%lx\n", header->fhd_gap);
- Printf ("header->fhd_flags: 0x%lx\n", header->fhd_flags);
- Printf ("header->fhd_speed: %ld\n", header->fhd_speed);
- Printf ("header->fhd_next: %ld\n", header->fhd_next);
- Printf ("header->fhd_frit: 0x%lx\n", header->fhd_frit);
- Printf ("header->fhd_expand: ");
-
- for (i = 0; i < FHD_EXPAND_SIZE; i++)
- Printf ("%lx ", 0xff & (unsigned int)header->fhd_expand[i]);
- Printf ("\n");
- }
- }
-
- void
- read_fheader (BPTR fd, struct frame_header *fheader)
- {
- unsigned char data[SIZE_FHEADER];
- unsigned char *buf = data;
- int syncNotFound = TRUE;
- int ret, i;
-
- i = 0; /* Syncronize to the magic word */
-
- do {
- ret = FGetC (fd);
- ++i;
-
- if (verbose)
- Printf ("Read1 i: %ld Byte: 0x%lx sync: %s\n",
- i, 0xff & (unsigned int)ret, syncNotFound?"TRUE":"FALSE");
-
- if (ret == (unsigned char)0xfa) {
- ret = FGetC (fd);
- ++i;
-
- if (ret == (unsigned char)0xf1)
- syncNotFound = FALSE;
- else
- syncNotFound = TRUE;
-
- if (verbose)
- Printf ("Read2 i: %ld Byte: 0x%lx sync: %ld\n",
- i, 0xff & (unsigned int)ret, syncNotFound);
- }
- } while ((syncNotFound == TRUE) && (ret >= 0));
-
- if (ret < 0) {
- Printf ("Error reading input file looking for"
- " frame header magic number. i: %ld\n", i);
- Quit (GET_ERR);
- }
- if (verbose)
- Printf ("After Sync i: %ld sync: %s ret: %ld\n",
- i, syncNotFound?"TRUE":"FALSE", ret);
-
- if ((ret = Seek (fd, -6, OFFSET_CURRENT)) < 0) {
- Printf ("Seeking to begining of frame\n");
- Quit (GET_ERR);
- }
- if (FRead (fd, buf, SIZE_FHEADER, 1) < 1)
- Quit (GET_ERR);
-
- fheader->fr_size = get_long(buf);
- fheader->fr_magic = get_short(buf);
- fheader->fr_chunks = get_short(buf);
-
- memcpy (buf, fheader->fr_expand, FR_EXPAND_SIZE);
-
- if (verbose) {
- Printf ("fheader->fr_size: %ld\n", fheader->fr_size);
- Printf ("fheader->fr_magic: 0x%lx\n", fheader->fr_magic);
- Printf ("fheader->fr_chunks: %ld\n", fheader->fr_chunks);
- Printf ("fheader->fr_expand: ");
-
- for (i = 0; i < FR_EXPAND_SIZE; i++)
- Printf ("%ld ", 0xff & (unsigned int)fheader->fr_expand[i]);
-
- Printf ("\n");
- }
- }
-
- static void inline
- read_chunk (BPTR fd, struct chunk_header *chunk)
- {
- unsigned char data[SIZE_CHEADER];
- unsigned char *buf = data;
-
- if (FRead (fd, buf, SIZE_CHEADER, 1) < 1)
- Quit (GET_ERR);
-
- chunk->ch_bytes = get_long(buf);
- chunk->ch_type = get_short(buf);
-
- if (verbose) {
- Printf ("chunk->ch_bytes: %ld\n", chunk->ch_bytes);
- Printf ("chunk->ch_type: %ld\n", chunk->ch_type);
- }
- }
-
- void
- interpret_fli (BPTR fd, /* The file descriptor */
- struct fli_header *header, /* The header of the file */
- unsigned char *data, /* A pointer to the pixel data */
- int notfirst, /* Is this not the first time through? */
- void (*func)() ) /* The function that stores or displays the chunks */
- {
- int i, j, s, l, k; /* Random look/status ints */
- int ndiff; /* To hold the # lines changed from last frame */
- struct frame_header fheader; /* To hold each frame header */
- struct chunk_header chunk; /* To hold each chunk header */
- unsigned char *buf = NULL; /* malloc'd space to hold each chunk */
- int bufalloc; /* Space already allocated for buf */
- int skchange, skcount, sicount; /* Various pixel/data index's */
- unsigned char *cptr,*dptr,*eptr; /* data pointers into *buf */
- int npack; /* Number of packets in this chunk */
- unsigned char by, by0, by1; /* To hold a byte */
- int curx, cury; /* The current x & y coords */
- int wwidth, wheight; /* Width and height of the window */
- int topy,bottomy,leftx,rightx; /* For optimizing FLI_LC chunks */
-
- static long twopos; /* To keep the file offset of frame # 2 */
-
- wwidth = header->fhd_width;
- wheight = header->fhd_height;
-
- for (i=0; i <= header->fhd_frames; i++)
- {
- /* if (SetSignal(0,0) & SIGBREAKF_CTRL_C)
- Quit (NO_ERR); */
-
- /* The following stuff ist only needed if we display the frames
- while we interpret the file */
-
- if ((notfirst) && (i==0)) /* If this is the first time through, */
- { /* we display frame # 1, */
- Seek (fd, twopos, OFFSET_BEGINNING);
- continue; /* otherwise, we skip right to frame two */
- }
-
- /* If this is the first time through and we are at frame #2,
- save our file offset for the next loop through */
-
- if (!(notfirst) && (i==1))
- twopos = Seek (fd, 0, OFFSET_CURRENT); /* lseek (fd, 0, 1); */
-
- /* Each frame has a header */
-
- read_fheader (fd, &fheader);
-
- for (j=0; j < fheader.fr_chunks; j++)
- {
- /* Each chunk also has a header */
-
- read_chunk (fd, &chunk);
-
- /* Malloc the space to hold whole chunk, unless it
- is a COPY chunk. Malloc/Realloc only if necessary */
-
- if (chunk.ch_type != FLI_COPY) {
- if (!buf)
- {
- if (!(buf = (unsigned char *)malloc(chunk.ch_bytes)))
- Quit (MEM_ERR);
- bufalloc = chunk.ch_bytes;
- }
- else
- {
- if (bufalloc < chunk.ch_bytes)
- {
- if (!(buf = (unsigned char *)realloc(buf, chunk.ch_bytes)))
- Quit (MEM_ERR);
- bufalloc = chunk.ch_bytes;
- }
- }
- }
-
- /* A COPY chunk means 64k of uncompressed image data,
- read it directly into the image */
-
- if (chunk.ch_type == FLI_COPY)
- s = FRead (fd, data, wwidth*wheight, 1);
- else
- s = FRead (fd, buf, chunk.ch_bytes-6, 1);
-
- if (s < 0) {
- Printf ("s: %ld fd: %lx data: 0x%lx chunk.ch_bytes: %ld\n",
- s, fd, data, chunk.ch_bytes);
- Quit (GET_ERR);
- }
-
- cptr = buf;
-
- switch (chunk.ch_type) {
-
- LONG line; /* just temporary */
-
- case FLI_COPY:
-
- #ifdef DEBUGGING
- printf("CP ww: %ld wh: %ld\n",wwidth,wheight);
- #else
- (*func)(FLI_COPY, i, data, 0,0, 0,0, wwidth,wheight);
- #endif
- break;
-
- /* A BLACK chunk */
-
- case FLI_BLACK:
- { /* ULONG *d = (ULONG *)data, anz = wwidth*wheight/4, z;
- for (z=0; z < anz; z++, *d++ = 0);
- */
-
- (*func)(FLI_BLACK, i, data, 0,0, 0,0, wwidth,wheight);
- }
- break;
-
- /* A COLOR chunk: A compressed colormap to be stored or changed */
-
- case FLI_256_COLOR:
-
- npack = get_short(cptr);
-
- for (l=0; l < npack; l++)
- {
- skcount = *(cptr++); /* # colors not to change */
- skchange = *(cptr++); /* # of colors to change */
-
- if (!skchange) /* (0 means all) */
- skchange=MAXCOL;
-
- (*func)(FLI_256_COLOR, i, cptr, skcount,
- skchange, 0,0, 0,0);
-
- cptr += skchange * 3;
- }
- break;
-
- case FLI_COLOR:
-
- npack = get_short(cptr);
-
- for (l=0; l < npack; l++)
- {
- skcount = *(cptr++); /* # colors not to change */
- skchange = *(cptr++); /* # of colors to change */
-
- if (!skchange) /* (0 means all) */
- skchange=MAXCOL;
-
- /* The colors are stored in the right 6 bits
- of the byte. We then convert it to a short. */
-
- (*func)(FLI_COLOR, i, cptr, skcount, skchange, 0,0, 0,0);
- cptr += skchange * 3;
- }
- break;
-
- /* Line compressed, and bytewise/run-length compressed
- chunks are similar. BRUN chunks always start at the
- top, while LC chunks can skip lines. Also, LC chunks
- can skip bytes on each line. The sign of the
- byte also has opposite meanings for the two! */
-
- case FLI_LC:
-
- curx = 0;
- cury = get_short(cptr); /* Lines at top to skip */
- ndiff = get_short(cptr); /* # of lines different */
-
- topy = cury;
- bottomy = cury + ndiff;
-
- leftx = wwidth;
- rightx = 0;
- line = (short)wwidth * (short)cury;
-
- for (k=0; k < ndiff; k++, line += wwidth) /* Go through each line */
- {
- npack = *(cptr++); /* # packets this line */
-
- for (l=0; l < npack; l++)
- {
- int i;
- skcount = *(cptr++); /* # bytes to skip */
-
- if (l == 0 && skcount < leftx)
- leftx = skcount;
-
- curx += skcount;
- dptr = data + line + curx;
-
- /* The number of bytes in this packet to change */
-
- sicount = *(cptr++);
-
- /* Positive, for LC means bytes that change follow,
- for BRUN means one byte to follow, spread it through. */
-
- if (sicount < 128)
- {
- i = sicount;
- while (i)
- {*(dptr++) = *(cptr++); i--;}
- }
- else /* Negative, the opposite */
- {
- sicount = 256 - sicount;
- by = *(cptr++);
- i = sicount;
- while (i)
- {*(dptr++) = by; i--;}
- }
- curx += sicount;
- } /* for (l=0; l < npack; l++) */
-
- if (curx > rightx)
- rightx = curx;
-
- cury++; /* Next line */
- curx = 0;
- } /* for (k=0; k < ndiff; k++) */
-
- #ifdef DEBUGGING
- printf("LC top: %ld bot: %ld left: %ld right: %ld\n",
- topy, bottomy, leftx, rightx);
- #else
- (*func)(FLI_LC, i, data,
- leftx,topy, leftx,topy,
- rightx-leftx,bottomy-topy);
- #endif
- break;
-
- case FLI_DELTA:
-
- curx = 0;
- cury = 0;
-
- by0 = *(cptr++);
- by1 = *(cptr++);
- ndiff = by0 + 256 * by1; /* # of lines different */
-
- /* printf(" -- -- ndiff: %ld frame: %ld\n",ndiff,i); */
-
- topy = 0; bottomy = 0;
-
- leftx = wwidth; rightx = 0;
-
- k=0;
- while (k < ndiff) /* Go through each line */
- {
- by0 = *(cptr++);
- by1 = *(cptr++);
- npack = by0 + 256 * by1;
-
- line = (short)wwidth * (short)cury;
-
- if (npack >= 32768) npack -= 65536;
-
- /* printf(" -- npack: %ld cury: %ld\n",npack,cury); */
-
- if (npack < 0) /* skip lines */
- {
- if (cury == 0)
- topy = -npack;
- cury -= npack;
- continue;
- }
- bottomy = cury+1;
-
- for (l=0; l < npack; l++)
- {
- int i;
-
- skcount = *(cptr++); /* # bytes to skip */
-
- if (l == 0 && skcount < leftx)
- leftx = skcount;
-
- curx += skcount;
-
- /* printf("pack: %ld curx: %ld skip: %ld\n",l,curx,skcount); */
-
- /* The number of words in this packet to change */
-
- sicount = *(cptr++);
-
- /* Positive, for DELTA means sicount words (16 bit)
- that change follow */
-
- i = 2 * sicount;
- dptr = data + line + curx;
-
- if (sicount < 128)
- {
- while (i)
- {*(dptr++) = *(cptr++); i--;}
- }
- else /* Negative, the opposite */
- {
- sicount = 256 - sicount;
- by0 = *(cptr++);
- by1 = *(cptr++);
- eptr = dptr + 2 * sicount;
-
- do {
- *(dptr++) = by0;
- *(dptr++) = by1;
- } while (dptr < eptr);
- }
- curx += 2 * sicount;
- }
-
- if (curx > rightx)
- rightx = curx;
-
- cury++; /* Next line */
- curx = 0;
- k++;
- }
-
- #ifdef DEBUGGING
- printf("DL top: %ld bot: %ld left: %ld right: %ld\n",
- topy, bottomy, leftx, rightx);
- #else
- (*func)(FLI_DELTA, i, data, leftx,topy, leftx,topy,
- rightx-leftx, bottomy-topy);
- #endif
- break;
-
- case FLI_BRUN:
-
- dptr = data;
- eptr = data + wwidth;
-
- for (k=0; k < wheight; k++, eptr += wwidth) /* Go through each line */
- {
- int i;
- cptr++; /* skip # packets (buggy PC-shit!) */
-
- while (dptr < eptr) {
-
- /* The number of bytes in this packet to change */
-
- sicount = *(cptr++);
-
- /* Positive, for LC means bytes that change follow,
- for BRUN means one byte to follow, spread it through. */
-
- if (sicount < 128)
- {
- i = sicount;
- by = *cptr++;
- while (i)
- {*(dptr++) = by; i--;}
- }
- else /* Negative, the opposite */
- {
- sicount = 256 - sicount;
- i = sicount;
- while (i)
- {*(dptr++) = *(cptr++); i--;}
- }
- }
- }
- #ifdef DEBUGGING
- printf("BR ww: %ld wh: %ld\n",wwidth,wheight);
- #else
- (*func)(FLI_BRUN, i, data, 0,0, 0,0, wwidth,wheight);
- #endif
- break;
-
- } /* switch */
-
- } /* for */
-
- /* Send a FLI_SYNC after each frame to get accurate timing */
-
- (*func)(FLI_SYNC, i, (unsigned char *)0, 0,0, 0,0, 0,0);
-
- } /* for (i=0; i <= header->fhd_frames; i++) */
-
- /* Only free the buffer if we allocated something */
-
- if (buf) { /* Damned shit was here before (!) */
- free (buf);
- buf = NULL;
- }
- }
-